Description
User marks favorite teams. Favorites float to the top of the main dashboard view. In a league view, always show each favorite's last result and next fixture, even outside the current window.
Acceptance Criteria
- #1 favorites pinned to top of dashboard
- #2 league view shows favorite last + next
- #3 favorites persist
Implementation Plan
Depends on TASK-004 config layer + team identity.
- model.Team gains ID string (ESPN team id); espn teamJSON.ID + mapTeam set it.
- App: cfg config.Config + favs map[string]bool (key=league+':'+teamID, fallback abbr). New() loads via config.Load(). Helpers favKey(league,team)/isFav(league,team)/toggleFav(league,team){mutate favs+cfg, config.Save best-effort}.
- Marking [detail view]: keys Fav(f)=toggle away, FavHome(F)=toggle home. Footer hint. Persist on toggle [AC#3].
- Cards: renderCard/teamRow take fav bool -> show โ before favorite team abbr (components.go). bodyLines passes a.isFav per side.
- Ordering (sections.go) [AC#1/#2]:
- all-leagues: prepend 'โ Favorites' section = today's games across leagues involving a favorite; remove those from their per-league section (no dup).
- single-league: prepend 'โ Favorites' bucket before Today/Upcoming/Past = for each favorite team in league, its live game + most-recent final (last) + next scheduled (next) found within fetched window; dedup.
- sections()/bodyLines() invariant preserved (bodyLines re-walks sections()).
- Out-of-window last/next (favorite's next match >7d away or last >2d ago) deferred to follow-up using ESPN team schedule endpoint -> new task.
- Tests: favKey stability; favorites-section selection from a fixture set.
Final Summary
Favorite teams: mark, persist, pin to top.
What changed:
- model.Team gains stable ESPN team ID (captured in espn mapping); favKey = league+':'+id (abbr fallback).
- App loads favorites from config on start; toggleFav persists immediately via config.Save (best-effort) [AC#3].
- Marking: in detail view, f toggles the away team, F the home team; footer hints added. โ shown next to favorite teams on dashboard cards and in the detail score box.
- Ordering [AC#1/#2]:
- All-leagues dashboard: a 'โ Favorites' section pinned on top with today's games involving a favorite, removed from their league section (no dupes).
- Single-league view: a 'โ Favorites' bucket above Today/Upcoming/Past showing each favorite's live game + most-recent final (last) + next scheduled fixture (next), drawn from the fetched window.
Scope note: last/next resolve within the per-league fetch window; matches further out are deferred to TASK-009 (per-team schedule endpoint).
Also in this branch (window infra): per-league fetch windows on model.League (MLB 3/5d, NFL 10/10d, soccer/default 5/10d) and a required &limit=300 on ScoreboardRange โ the latter also fixes a latent bug where dense slates were silently truncated to ESPN's default cap.
Tests: ui/favorites_test.go (favKey identity, hasFav, favoriteHighlights live/next/last selection + dedup + non-fav exclusion). All packages build/vet/test clean.